package com.springboot.code.config;

import com.alibaba.fastjson.JSON;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * DESC:
 *
 * @author WangJie
 * @date Created in 2023-05-21 13:52
 */
@Aspect
@Component
public class WebLogAspect {

    private final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);

    ThreadLocal<Long> startTime = new ThreadLocal<>();

    /**
     * 定义切入点，以controller下所有包的请求为切入点
     * execution(* com.coffee..UserService.*(..))
     */
    @Pointcut ("execution(* com.springboot.code..controller.*.*(..))")
    public void webLog() {

    }

    /**
     * 前置通知：在切入点之前执行的通知
     */
    @Before ("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        startTime.set(System.nanoTime());
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert servletRequestAttributes != null;
        HttpServletRequest request = servletRequestAttributes.getRequest();
        HttpSession session = (HttpSession) servletRequestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
        if (session != null) {
            logger.info("会话编号: [{}]", session.getId());
        }
        logger.info("请求地址: [{}] {}", request.getMethod(), request.getRequestURL().toString());
        logger.info("执行方法: {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
        try {
            logger.info("请求参数: {}", JSON.toJSONString(joinPoint.getArgs()[0]));
        } catch (Exception e) {
            logger.error("REQUEST BODY PARSE ERROR!");
        }
    }

    /**
     * 环绕通知
     * 环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型
     */
    @Around ("webLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long startTime = System.nanoTime();
        Object result = proceedingJoinPoint.proceed();
        String resultStr = JSON.toJSONString(result);
        logger.info("响应参数: {}", resultStr);
        logger.info("执行耗时: {}ms", (System.nanoTime() - startTime)/1000000);
        return result;
    }

}
